#include "TcpServer.h"


TcpServer::TcpServer(const std::string& ip, const uint16_t port, int threadNum)
:threadNum_(threadNum), main_loop_(new EventLoop(true)), acceptor_(main_loop_.get(), ip, port), threadPool_(threadNum_, "IO")
{
    main_loop_->set_epoll_TimeOut_CallBack(std::bind(&TcpServer::epoll_TimeOut, this, std::placeholders::_1));
    acceptor_.setNewConnectionCb(std::bind(&TcpServer::new_Connection,this,std::placeholders::_1));

    //创建从事件循环,放入容器中
    for (int idx = 0; idx < threadNum_; idx++)
    {
        sub_loops_.emplace_back(new EventLoop(false, 5, 10));
        sub_loops_[idx]->set_epoll_TimeOut_CallBack(std::bind(&TcpServer::epoll_TimeOut, this, std::placeholders::_1));
        sub_loops_[idx]->setTimerCallBack(std::bind(&TcpServer::removeConn,this, std::placeholders::_1));   //设置清除空闲Tcp连接的回调函数
        threadPool_.addtask(std::bind(&EventLoop::run, sub_loops_[idx].get()));  //在线程池中运行从事件循环
    }
}

TcpServer::~TcpServer()
{
    //delete acceptor_;
    //delete main_loop_;

    //改为智能指针后无需再手动管理内存
/*
    //释放map容器中的Connection对象
    for(auto &idx : conns_)
    {
        delete idx.second;
    }
*/
    //释放从事件循环
    // for(auto &idx:sub_loops_)
    // {
    //     delete idx;
    // }

    //释放线程池
    //delete threadPool_;
}

//运行事件循环
void TcpServer::start()
{
    main_loop_->run();
}

//停止IO线程和事件循环
void TcpServer::stop()  
{
    //停止主事件循环
    main_loop_->stop();
    printf("主事件循环已停止\n");
    //停止从事件循环
    for(int idx = 0; idx < threadNum_; idx++)
    {
        sub_loops_[idx]->stop();
    }
    printf("从事件循环已停止\n");
    //停止IO线程
    threadPool_.stop();
    printf("IO线程已停止\n");
}  

//处理新客户端连接请求
void TcpServer::new_Connection(std::unique_ptr <Socket> clientSock)
{
    
    //Connection *conn = new Connection(main_loop_, clientSock);
    //把新建的conn分配给从事件循环
    spConnection conn(new Connection(sub_loops_[clientSock->fd() % threadNum_].get(), std::move (clientSock)));
    conn->set_closeCallBack(std::bind(&TcpServer::close_Connection, this, std::placeholders::_1));
    conn->set_errorCallBack(std::bind(&TcpServer::error_Connection, this, std::placeholders::_1));
    conn->set_onMessageCallBack(std::bind(&TcpServer::on_Message, this, std::placeholders::_1, std::placeholders::_2));
    conn->set_sendCompleteCallBack(std::bind(&TcpServer::send_Complete, this, std::placeholders::_1));
    
    //放入map容器
    {   //上锁
        std::lock_guard<std::mutex> gd(mmutex_);
        conns_[conn->fd()] = conn;
    }
    sub_loops_[conn->fd() % threadNum_]->newConnection(conn);     //把conn存放到EventLoop的map容器中
    if(new_Connection_Cb_) new_Connection_Cb_(conn);       //回调EchoServer中的函数
}

void TcpServer::close_Connection(spConnection conn)          //关闭客户端的连接，在Connection类中回调此函数
{
    if(close_Connection_Cb_) close_Connection_Cb_(conn);
    
    
    {   //上锁
        std::lock_guard<std::mutex> gd(mmutex_);
        conns_.erase(conn->fd());   //从map容器中删除conn
    }   

}

void TcpServer::error_Connection(spConnection conn)          //客户端的连接错误，在Connection类中回调此函数
{
    if(error_Connection_Cb_) error_Connection_Cb_(conn);

    {   //上锁
        std::lock_guard<std::mutex> gd(mmutex_);
        conns_.erase(conn->fd());   //从map容器中删除conn
    } 
}

//处理客户端的请求报文，在Connection中回调该函数
void TcpServer::on_Message(spConnection conn, std::string& message)    
{
    if(on_Message_Cb_) on_Message_Cb_(conn, message);
/*
    message = "reply:" + message;
    int len = message.size();
    std::string tmpbuf((char*)&len, 4); //填充报文头部
    tmpbuf.append(message);             //填充回应报文内容
    //把临时缓冲区的数据发生出去
    conn->send(tmpbuf.data(), tmpbuf.size());
*/
}

void TcpServer::send_Complete(spConnection conn)              //数据发送完成的函数
{
    if(send_Complete_Cb_) send_Complete_Cb_(conn);
}

//epoll_wait()超时，在EventLoop类中回调此函数
void TcpServer::epoll_TimeOut(EventLoop* loop)
{
    if(timeout_Cb_) timeout_Cb_(loop);
}

void TcpServer::set_new_Connection_Cb_(std::function<void(spConnection)> func)
{
    new_Connection_Cb_ = func;
}

void TcpServer::set_close_Connection_Cb_(std::function<void(spConnection)> func)
{
    close_Connection_Cb_ = func;
}

void TcpServer::set_error_Connection_Cb_(std::function<void(spConnection)> func)
{
    error_Connection_Cb_ = func;
}

void TcpServer::set_on_Message_Cb_(std::function<void(spConnection, std::string &message)> func)
{
    on_Message_Cb_ = func;
}

void TcpServer::set_send_Complete_Cb_(std::function<void(spConnection)> func)
{
    send_Complete_Cb_ = func;
}

void TcpServer::set_timeout_Cb_(std::function<void(EventLoop*)> func)
{
    timeout_Cb_ = func;
}

//删除Conns_中的Connection对象，在EventLoop::handletimer()中将回调此函数
void TcpServer::removeConn(int fd)
{
    {   //上锁
        std::lock_guard<std::mutex> gd(mmutex_);
        conns_.erase(fd);   //从map容器中删除conn
    } 
} 
